import { asyncRouterMap, constantRouterMap, router404Map } from '@/router';
import * as userApi from '@/services/api/user';
import { setLogin } from '@/utils/auth';
import { authDataPermissionMenuListGetApi } from '@/services/api/permission';
/**
 * 通过meta.role判断是否与当前用户权限匹配
 * @param route
 * @param menus
 */
function hasPermission(route, menus) {
  menus = _.isArray(menus) ? menus : [];
  return menus.some((item) => {
    const subList = item.children || [];
    // 找到菜单
    if (route.name == item.keyword) { // 不同顶级路由下，子路由keyword有重复的情况，那么需要注意，不能跨路由匹配
      route.asyncChildren = subList;// 记录路由子节点中，已配置的后台权限信息,可能包含的是菜单，也可能是按钮,用于子路由的权限判断
      return true;
    }
    // 有子菜单
    // if (subList.length > 0) return hasPermission(route, subList);

    return false;
  });
}

/**
 * 递归过滤异步路由表，返回符合用户角色权限的路由表
 * @param asyncRouterMap 配置的权限合集
 * @param menus 用户拥有的权限合集
 */
function filterAsyncRouter(asyncRouterMap, menus) {
  const accessedRouters = asyncRouterMap.filter((route) => {
    if (hasPermission(route, menus)) {
      // 当前菜单有权限，
      // 1.继续判断其子菜单
      if (route.children && route.children.length) {
        // 有children的route配置权限对应一个目录菜单项，不会包含按钮级别的权限
        // 不同顶级路由下，子路由keyword有重复的情况，那么需要注意，不能跨顶级路由匹配
        route.children = filterAsyncRouter(route.children, route.asyncChildren);
      } else if (route.meta && (!route.asyncChildren || (route.asyncChildren && route.asyncChildren.length == 0))) {
        // 没有children的route配置权限对应一个页面菜单项，有可能包含按钮级别的权限
        // 所有没有asyncChildren时，说明用户不具备相应的所有按钮级别权限配置
        route.meta.roles = [];
      }
      // 2.获取当前菜单的子按钮级别权限route.meta.role
      filterAsyncRoles(route);

      return true;
    }
    return false;
  });
  return accessedRouters;
}

/**
 *
 * @param roles 页面已定义的按钮级别权限汇总
 * @param menus 用户已被授权的菜单及权限
 */
function filterAsyncRoles(route) {
  const { asyncChildren } = route;// 校验当前菜单权限时赋值
  if (route.meta && route.meta.roles && route.meta.roles.length > 0 && asyncChildren && asyncChildren.length > 0) {
    const wholeRoles = route.meta.roles;// 缓存页面已定义的按钮级别权限
    const asyncRoles = []; // 异步获取的权限
    const flattenedRoles = flattenAsyncChildren(asyncChildren);
    _.each(flattenedRoles, (item) => {
      if (_.includes(wholeRoles, item.keyword)) {
        asyncRoles.push(item.keyword);
      }
    });
    route.meta.roles = asyncRoles;
  }
}

function flattenAsyncChildren(asyncChildren) {
  let flattenedChildren = [];
  _.each(asyncChildren, (item) => {
    flattenedChildren.push(item);
    if (item.children) {
      flattenedChildren = flattenedChildren.concat(flattenAsyncChildren(item.children));
    }
  });
  return flattenedChildren;
}

const permission = {
  state: {
    routers: constantRouterMap,
    addRouters: [],
    userPermissionTree: [],
    dataPermissionList: [],
  },
  mutations: {
    SET_ROUTERS: (state, routers) => {
      state.addRouters = routers.concat(router404Map);
      state.routers = constantRouterMap.concat(routers).concat(router404Map);
    },
    SET_USER_PERMISSION_TREE: (state, routers) => {
      state.userPermissionTree = routers.concat(router404Map);
    },
    // 保存数据权限数据
    SET_DATA_PERMISSION_LIST: (state, dataPermissionList) => {
      state.dataPermissionList = dataPermissionList;
    },
  },
  actions: {
    // 有网络时调用
    GenerateRoutesWithMenus({ commit }, data) {
      return new Promise((resolve) => {
        let accessedRouters;
        accessedRouters = filterAsyncRouter(asyncRouterMap, data);
        commit('SET_ROUTERS', accessedRouters);
        commit('SET_USER_PERMISSION_TREE', accessedRouters);
        resolve();
      });
    },
    // 没有网络时调用
    GenerateRoutesWithMenusWithoutNet({ commit }, data) {
      return new Promise((resolve) => {
        let accessedRouters;
        commit(types.SET_ADMIN_MENUS, data);
        accessedRouters = asyncRouterMap;
        commit('SET_ROUTERS', accessedRouters);
        commit('SET_USER_PERMISSION_TREE', accessedRouters);
        resolve();
      });
    },
    // 数据权限
    async getDataPermissionList({ commit }) {
      const [result, data] = await authDataPermissionMenuListGetApi();
      if (result !== false) {
        commit('SET_DATA_PERMISSION_LIST', data);
      }
    },
  },
};

export default permission;
